Skip to content

CMUX-37 final push: close five 2026-05-03 smoke-test gaps - #118

Merged
BenevolentFutures merged 9 commits into
mainfrom
cmux-37/final-push
May 4, 2026
Merged

BenevolentFutures merged 9 commits into
mainfrom
cmux-37/final-push

Conversation

@BenevolentFutures

Copy link
Copy Markdown
Contributor

Summary

Closes the five gaps surfaced by the 2026-05-03 smoke-test of CMUX-37 (/tmp/cmux-37-smoke-report.md). Phases 0 to 5 already landed via PRs #75, #77, #78, #79; this is the final close-out so the ticket can move review to done.

Workstreams (9 commits, 5 substantive + 2 housekeeping)

W1: blueprint markdown parser/writer, default to ~/.config/c11/

  • be80a504 blueprint markdown parser + writer
  • 7911a41e c11 directory + markdown default; legacy paths still read

W2: snapshot --all writes a manifest envelope, restore polymorphic on id

  • aea6eaa8 snapshot manifest on --all; restore polymorphic on manifest id

W3: silence bogus failure: lines on clean restore (metadata_override + seed terminal cwd)

  • 8fb86dd7 capture: drop redundant title metadata
  • 3629b310 cli: classify expected restore diagnostics as info

W4: c11 workspace <sub> --help two-level dispatch

  • a30e6b8c workspace --help routing

W5: CLI honors C11_SOCKET

  • d0d85f42 cli: honor C11_SOCKET; log auto-discovery to stderr

Housekeeping

  • 314f4687 refresh plan: five-workstream close-out
  • 6c77018b capture orchestrator handoff plan + lattice state

Diff scope

16 files, +2843/-891. Mostly Swift sources under Sources/Workspace* plus matching tests in c11Tests/.

Test plan

  • CI green on cmux-37/final-push
  • Tagged-build re-run of the original smoke scenarios from /tmp/cmux-37-smoke-report.md:
    • Scenario 1 round-trip: zero failure: lines on a clean restore
    • Scenario 2 snapshot --all: one manifest plus inner snapshots; restore <set-id> rebuilds all workspaces
    • Scenario 3 blueprint export defaults to markdown under ~/.config/c11/blueprints/
    • Scenario 4 c11 workspace new --help and c11 workspace export-blueprint --help route correctly
    • C11_SOCKET=... is honored by the CLI; legacy CMUX_SOCKET still works
  • Trident code review of the 9-commit diff before merge

🤖 Generated with Claude Code

BenevolentFutures and others added 9 commits May 3, 2026 14:55
Final-Push Plan section drafted by orchestrator pre-handoff covers all
five workstreams (markdown blueprints, manifest layer, diagnostic
cleanup, workspace --help routing, C11_SOCKET safety) with commit
grouping, parallelization table, acceptance criteria, and Do-NOT-ship
list. Delegator phase begins from this state.
Captures the prior delegator session's plan rewrite plus the Lattice state
changes (status/comments) that went with it. The plan replaces the older
phase-based shape with a single five-workstream close-out PR:

  1. Markdown blueprint format
  2. Snapshot manifest layer for `--all`
  3. Restore diagnostic cleanup
  4. `c11 workspace --help` routing fix
  5. CLI socket safety (`C11_SOCKET` + auto-discovery breadcrumb)

Driven by the 2026-05-03 smoke validation report
(/tmp/cmux-37-smoke-report.md) on tagged build cmux-37-smoke.
Original ticket Phases 0–5 already shipped via PRs #75 and #79.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…pace <sub> --help`

`c11 workspace new --help` previously printed `Unknown command 'workspace'`
because the help dispatcher had no entry for `workspace`. Add a `case
"workspace":` to subcommandUsage that recognizes the three real subcommands
(apply, new, export-blueprint), thread `commandArgs` through so the
sub-token resolves, and update dispatchSubcommandHelp to include the
resolved subcommand in the header. Top-level usage gains the four
workspace lines too.

Workstream 4 of the five-workstream close-out (smoke report 2026-05-03).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New `Sources/WorkspaceBlueprintMarkdown.swift` provides Foundation-only
parse/serialise for the operator-approved markdown blueprint format
(Obsidian-friendly frontmatter + fenced YAML layout block). A vendored
tiny YAML subset parser handles the indented mapping/list grammar the
schema needs without an external SwiftPM dependency.

`WorkspaceBlueprintStore.read(url:)` and `write(_:to:)` now dispatch on
the URL extension: `.md` files round-trip through the new parser, JSON
files keep the existing path. `indexEntries` reads the markdown
frontmatter to populate name and description (falling back to filename
stem when the frontmatter is missing or unparseable), so .md blueprints
appear in the picker with their authored titles.

Round-trip semantics: name ↔ frontmatter title; description ↔
frontmatter description; workspace.customColor ↔ custom_color;
workspace.title falls back to frontmatter title unless `workspace_title`
is set explicitly. SurfaceSpec metadata, paneMetadata, and description
are dropped on serialise — markdown is the hand-authored, legible form;
fully-faithful captures stay on the JSON path. Per-repo and per-user
discovery still scan only the legacy `.cmux` paths in this commit; the
filesystem rename to `.c11`/`~/.config/c11/blueprints/` lands in the
next commit alongside the exporter and CLI integration.

Tests cover round-trip equality at the value level (single-leaf,
horizontal split, nested split mirroring the operator schema), custom
color preservation, separate workspace_title, schema-example parse,
and error surface for missing layout section / missing fenced block /
unknown surface kind / split without children. Plus a store-level .md
round-trip and an updated .md picker test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ll read

Switch the canonical blueprint write target from
~/.config/cmux/blueprints/<name>.json to
~/.config/c11/blueprints/<name>.md. Markdown is the default format;
operators who still want JSON pass --format json (also threaded over
the v2 workspace.export_blueprint method as a format param).

Per-user discovery now scans both the new and the legacy directory; the
new directory ships first so the picker prefers canonical files when
both exist. Per-repo discovery walks .c11/blueprints/ alongside
.cmux/blueprints/ at each ancestor — .c11/ entries lead the merged
list. Legacy JSON envelopes at ~/.config/cmux/blueprints/*.json
remain discoverable and applicable; the smoke acceptance criteria
require this.

runWorkspaceBlueprintNew and workspaceBlueprintPicker now sniff the
file extension on --blueprint / picker selection. .md files are
routed through a new pure workspace.parse_blueprint v2 method that
parses content received in memory and returns the plan dict — keeping
the markdown parser inside the app's link surface, not the CLI binary,
and not turning the parse path into another arbitrary-file-read.
.json files keep the existing in-process JSONSerialization path.

Help text under `c11 workspace new --help` and
`c11 workspace export-blueprint --help` is updated to name the c11
canonical paths, list both file extensions, document --format, and
show an .md example.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Workstream 5 of the CMUX-37 close-out. Closes the wrong-socket footgun
the smoke validator hit on 2026-05-03: orchestrator set C11_SOCKET=...,
CLI read CMUX_SOCKET_PATH instead, fell through to auto-discovery via
last-socket-path, and silently mutated the operator's live workspace.

Changes:
- Socket-path resolution precedence is now: --socket → C11_SOCKET →
  CMUX_SOCKET_PATH → CMUX_SOCKET → auto-discovery. Both legacy keys
  remain accepted for back-compat (no deprecation warning yet — the
  plan defers that).
- Three call sites updated consistently: defaultSocketPath, run()'s
  env-var loop, claudeTeamsResolvedSocketPath. CLISocketSentryTelemetry
  also reads C11_SOCKET first so the breadcrumb context is accurate.
- After socket.path.autodiscovered fires, c11 now prints one stderr
  line attributing the resolved socket. CLISocketPathResolver gains a
  best-effort discoverySourceHint() that names the pointer file
  (last-socket-path) when the resolver matched it, or the CMUX_TAG=...
  derivation when matching a tag-derived candidate. Falls back to a
  generic "(auto-discovered)" suffix when the source is unclear.
- C11_QUIET_DISCOVERY=1 (any non-empty, non-"0" value) suppresses the
  stderr line. A global --quiet flag would touch every command's print
  loop; that's deferred per the plan's "Out of scope" note.
- usage() gains a Socket Path subsection and the Environment block now
  documents C11_SOCKET, CMUX_SOCKET_PATH, CMUX_SOCKET, and
  C11_QUIET_DISCOVERY.

New String(localized:) keys for the Translator phase:
- cli.socket.autoDiscoveredWithSource —
  "c11: using socket %@ (auto-discovered from %@)"
- cli.socket.autoDiscovered —
  "c11: using socket %@ (auto-discovered)"

Build: c11-cli scheme compiles clean against impl-A's commit
7911a41 at HEAD.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Workstream 3 of the CMUX-37 close-out, apply-side / CLI-side. The smoke
validator on 2026-05-03 saw `c11 restore <id>` exit 0 but emit seven
`failure:` lines for behaviors the executor deliberately reports on
every clean round trip — six `metadata_override` (one per surface with
a title) plus one `working_directory_not_applied` for the seed
terminal. Operator framing: stop scaring automation that grep-greps
for `failure:`.

Approach: Option B from the plan (CLI-side reclassification). The
ApplyFailure wire shape stays bit-exact — only the human-readable
print classifies. A future caller with a different opinion can read
the structured payload and ignore the classification.

Changes (CLI/c11.swift):
- Add CMUXCLI.FailureSeverity (.failure | .info) and two static
  helpers: failureSeverity(code:message:) and partitionFailures(_:).
  partitionFailures preserves the original order for stable output.
- Two codes get reclassified as .info:
  - `metadata_override` — fires when SurfaceSpec carries both .title
    and metadata["title"]. The capture-side fix (next commit) strips
    the dup; this is the belt for the suspenders.
  - `working_directory_not_applied` whose message contains
    "seed terminal reuse" — fires on every restore whose first
    terminal had a captured cwd. The seed shell is already running by
    the time the executor sees the spec, so the cwd cannot apply.
    Other emission sites (browser/markdown split, in-pane creation)
    stay classified as real failures.
- Three print sites updated to partition-then-print:
  - runWorkspaceApply (~L2975)
  - runWorkspaceBlueprintNew (~L3045)
  - runSnapshotRestore (~L3466)
  Real failures keep their existing prefix ("failures: N" or
  "  failure: ..."); info-level entries print under "info: N" or
  "  info: ...". Format consistency with the existing prefix per
  call site is preserved.
- DEBUG-only test hooks (debugFailureSeverityForTesting,
  debugPartitionFailuresForTesting) on CMUXCLI for future c11-cli
  test infrastructure.

CAUTION: detection of the seed-terminal case relies on the executor's
emitted message containing the substring "seed terminal reuse". If
Sources/WorkspaceLayoutExecutor.swift's
reportWorkingDirectoryNotApplicable call for the seedTerminal context
(around L656) ever changes its `context:` argument, update the matcher
in failureSeverity().

Tests: skipped — CMUXCLI lives in the c11-cli target only; c11Tests
links the c11 module, so unit-testing partitionFailures from there
would require adding c11.swift (~17k LoC) to the test target's build
phase or a new shared file with cross-target build-phase membership.
The classifier is testable via the smoke fixture during the Validate
phase (acceptance criterion: `c11 restore <id>` on the mixed
6-surface fixture prints `failures: 0`). DEBUG hooks are wired so
future c11-cli test infrastructure can exercise the partition.

No new String(localized:) keys. Existing print prefixes (`failures:`,
`failure:`) are not localized in the surrounding code, so the new
`info:` prefix follows that convention.

Build: c11-cli scheme compiles clean.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…erride warnings

Workstream 3 of the CMUX-37 close-out, capture-side. Pair to the
preceding CLI-side reclassification (3629b31). Together they close
the gap where every clean snapshot/restore round trip emitted six
bogus `metadata_override` "failure:" lines.

Root cause:
- Sources/WorkspaceLayoutExecutor.swift has dedicated setters for the
  canonical `title` (workspace.setPanelCustomTitle) and `description`
  (a separate write) fields. After they fire, it iterates
  spec.metadata and re-writes everything via SurfaceMetadataStore in
  merge mode. When metadata["title"] is also set and spec.title is
  non-nil, the executor flags this as an override even though the
  values usually agree — the dup is a round-trip artifact, not a real
  conflict.
- WorkspacePlanCapture reads `surfaceMetadata` (which contains the
  canonical "title" key, written through SurfaceMetadataStore by
  setPanelCustomTitle) AND sets SurfaceSpec.title from
  workspace.panelCustomTitles. Both make it onto the wire; the
  executor sees both and warns on every restore.

Fix:
- Add a private strippingRedundantCanonicalFields helper to
  WorkspacePlanCapture.Walker. It drops metadata["title"] (and
  metadata["description"]) when the metadata value matches the
  canonical SurfaceSpec field exactly — preserving the divergent case
  (operator wrote `set-metadata --key title --value "Foo"` separate
  from `set-title "Bar"`) where the override warning is a real signal.
- Call the helper from walkPane before constructing SurfaceSpec.
  Description is unconditionally nil from capture today, so the
  description branch is a no-op for now; the symmetry is intentional
  for when capture starts promoting description into spec.description.

Build: c11 scheme compiles clean against my WS3a commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…nifest id

`c11 snapshot --all` keeps writing N independent per-workspace files
and now ALSO writes a manifest at
`~/.c11-snapshots/sets/<set_id>.json` listing the inner ids with
set-level metadata (set id, capture time, c11 version, which workspace
was selected). The new `WorkspaceSnapshotSetFile` envelope is a pure
pointer file — each inner snapshot stays independently restorable
through the existing `c11 restore <inner-id>` path; nothing is
duplicated.

`c11 restore <id>` is now polymorphic. The CLI probes
`~/.c11-snapshots/sets/<id>.json` first; when that exists the request
goes to the new `snapshot.restore_set` v2 method, which reads the
manifest and runs each inner snapshot through
`WorkspaceLayoutExecutor` in capture order, re-establishing the
selected workspace at the end (subject to the socket focus policy).
`--in-place` is rejected for set restores: a set creates several
fresh workspaces and there is no single target to replace.
Path-on-disk targets are classified by content (`set_id` +
`snapshots` → manifest, `snapshot_id` + `plan` → single
snapshot) and staged into the matching default location before the v2
call.

`c11 list-snapshots` grows two flags: `--sets` switches to the
manifest table (SET_ID, CREATED_AT, COUNT, C11_VERSION); `--all`
prints both tables back-to-back. The default output is unchanged.

New v2 methods: `snapshot.restore_set`, `snapshot.list_sets`. The
`sets/` subdirectory is naturally excluded from per-snapshot
enumeration (the existing `enumerate(directory:source:)` is
non-recursive). New unit test rounds the manifest envelope through
Codable, asserts snake_case wire keys, and confirms `selected: false`
is wire-omitted on the common case.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@BenevolentFutures
BenevolentFutures merged commit cbae93d into main May 4, 2026
7 of 10 checks passed
@BenevolentFutures BenevolentFutures mentioned this pull request May 5, 2026
3 tasks
BenevolentFutures added a commit that referenced this pull request May 5, 2026
Patch release covering two PRs landed since v0.45.1:

- #121: socket-handler self-deadlock fix (EXC_BREAKPOINT crash, 4× on
  2026-05-04). Routes 99 v1 handlers in TerminalController.swift and
  12 in ThemeSocketMethods.swift through v2MainSync / Self.mainSync,
  which short-circuit when already on main, so they're correct under
  both pre- and post-C11-26 dispatcher paths.
- #118: CMUX-37 final push. Workspace blueprint markdown writer,
  snapshot --all manifest envelope with polymorphic restore, two-level
  workspace --help dispatch, CLI honors C11_SOCKET (legacy CMUX_SOCKET
  still works), redundant restore failure: lines reclassified as info.
BenevolentFutures added a commit that referenced this pull request May 5, 2026
Lattice ticket task_01KPMTEY4WGECM9MNZ4XARN7Y6 transitions to done after
PR #118 ("CMUX-37 final push: close five 2026-05-03 smoke-test gaps")
shipped on 2026-05-04. The orchestrator never recorded the merge on the
ticket; this catches the bookkeeping up.

Archive notes/archive/cmux-37/ preserves five generations of trident
review packs (2026-04-24 through 2026-05-04) that drove the ticket and
were unique to the cmux-37/* worktrees. Also archives the orphan C11-14
"CMUX-37 Phase 1 follow-up" task record from the cmux-37-phase1
worktree — its work shipped via PR #78 but the Lattice file never
reconciled with main, and the C11-14 short_id has since been reassigned
to a different ticket. Re-importing it would collide; preserved here
as historical record instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant